﻿using UnityEngine;
using System;
using System.Net.Sockets;
using System.Net;
using System.Collections.Generic;
using System.Net.Sockets;
using System;
using System.Collections;
using System.Net;
using System.Threading;
using UnityEngine;

public class PollIO : CThread
{
   
    public bool          m_bRun = true;
    public  PollIO       mPollIO = null;
    private const int    m_dwRecvSize = 4096;
    private const int     m_dwSendSize = 4096;

    private Socket myTcpClient = null;
   

    public ManualResetEvent connectDone = new ManualResetEvent(false);

    private LinkedList<GameMsg> sendList = new LinkedList<GameMsg>();

    private byte[] m_szBuffer = new byte[m_dwRecvSize];

    private ByteBuffer readBuffer = null;

    private SocketManager socketManager;

    public ManualResetEvent sendDone = new ManualResetEvent(false);

    private ByteArray m_pSendBytes = new ByteArray(m_dwSendSize);

    private List<ByteArray> m_szWaitData = new List<ByteArray>();

    private object m_pLock = new object();
    /// <summary>
    /// 已经发送的字节数
    /// </summary>
    private int m_nSendByteNumber = 0;

    public PollIO(SocketManager socketManager)
    {
            readBuffer = ByteBuffer.Allocate(m_dwRecvSize);
            this.socketManager = socketManager;
            m_bRun = true;
    }

    private void asyncread()
    {
		try
		{
                myTcpClient.BeginReceive(m_szBuffer, 0, m_szBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
        }
		catch (Exception localException)
		{
			Debug.Log(localException.Message);
            SocketManager.GetInstance().PushEvent(EvtType.netevt_fail);
        }
    }

    private void ReceiveCallback(IAsyncResult result)
    {
        try
        {
            int readbytes = myTcpClient.EndReceive(result);
            if (readbytes > 0)
            {
                readBuffer.WriteBytes(m_szBuffer, 0, readbytes);
            }
            while (true)
            {
                if (readBuffer.ReadableBytes() < 6)
                {
                    break;
                }
                readBuffer.MarkReaderIndex();
                int lengthHead = readBuffer.ReadInt();//长度头4字节
                short code = readBuffer.ReadShort();//消息ID 2字节
               // Debug.Log("recv:" + code);
                int dataLen = lengthHead - 2;//消息内容长度
                if (m_dwRecvSize > 0 && lengthHead > m_dwRecvSize)
                {
                    readBuffer.ResetReaderIndex();
                    SocketManager.GetInstance().PushEvent(EvtType.netevt_fail);
                    break;
                }
                if (dataLen > 0 && readBuffer.ReadableBytes() < dataLen)
                {
                    readBuffer.ResetReaderIndex();
                    break;
                }
                byte[] contentData = new byte[dataLen];
                readBuffer.ReadBytes(contentData, 0, contentData.Length);
                GameMsg message = new GameMsg(code, new ByteBuffer(contentData));
                
                DateTime dt = DateTime.Now;
                if (message.Code == GameMsgCode.Heart_Req)
                {//收到服务器心跳
                    ByteBuffer byteBuffer = ByteBuffer.Allocate(0);
                    this.SendNow(new GameMsg(GameMsgCode.Heart_Rsp, byteBuffer));
                    //Debug.Log("收到服务器心跳" + dt);
                }
                else if (message.Code == GameMsgCode.Heart_Rsp)
                {//收到服务器心跳回复
                   // Debug.Log("收到发给服务器心跳回复"+ dt);
                    socketManager.ReSetTime();
                }
                else if (message.Code == GameMsgCode.Gate_UserLogin)
                {
                    Debug.Log("recv用户登录:" + dt);
                }
                else if (message.Code == GameMsgCode.Center_RoleHallDataRefresh)
                {
                    Debug.Log("recv刷新大厅:" + dt);
                }
                else
                {
                    Debug.Log("  recv other:" + message.Code);
                }
            }

        }
        catch (Exception e)
        {
            Debug.Log("recv error:" + e.Message);
            SocketManager.GetInstance().PushEvent(EvtType.netevt_fail);
        }
        finally
        {
            asyncread();
        }
       
    }


    public void asyncwrite()
    {
        try
        {
            //Debug.Log("sendList"+ sendList.Count);
            if (sendList.Count != 0)
            {
                GameMsg gameMsg = sendList.First.Value;
                //Debug.Log("send:" + gameMsg.Code + ":" + sendList.Count);
                ByteArray szBytes = new ByteArray(0);
                byte[] bytes = encoder(gameMsg);
                OnSendData(bytes);
            }
            else
            {
                Thread.Sleep(1000);
                asyncwrite();
            }
        }
        catch (Exception localException)
        {
            Debug.Log(localException.Message);
            Close();
        }
    }

    /// <summary>
    /// 开始发送数据,如有尚未发完的数据,则加入队列
    /// </summary>
    /// <param name="methodID">调用远程的函数名称</param>
    /// <param name="szParam">调用远程的参数数组</param> 
    public bool OnSendData(byte[] bytes)
    {
        try
        {
            ByteArray szBytes = new ByteArray(0);
            szBytes.WriteBytes(bytes, bytes.Length);
            if (szBytes.length > m_dwSendSize)
            {
                List<ByteArray> bytearrays = new List<ByteArray>();
                szBytes.position = 0;
                while (szBytes.position < szBytes.length)
                {
                    ByteArray bytearray = new ByteArray(0);
                    int length = m_dwSendSize;
                    if (szBytes.length - szBytes.position < m_dwSendSize)
                        length = szBytes.length - szBytes.position;
                    szBytes.ReadBytes(bytearray, length);
                    bytearrays.Add(bytearray);
                }
                if (m_pSendBytes.position != 0)
                {
                    bytearrays.ForEach(p =>
                    {
                        m_szWaitData.Add(p);
                    });
                    return true;
                }
                szBytes = bytearrays[0];
                for (int i = 1; i < bytearrays.Count; i++)
                    m_szWaitData.Add(bytearrays[i]);
            }
            if (m_pSendBytes.position != 0)
            {
                m_szWaitData.Add(szBytes);
                return true;
            }
            m_pSendBytes.WriteBytes(szBytes, 0, szBytes.length);
            m_pSendBytes.position = 0;
            return OnSend();
        }
        catch (Exception e)
        {
            return false;
        }
    }


    /// <summary>
    /// 正式发送数据
    /// </summary>
    /// <returns></returns>
    private bool OnSend()
    {
        try
        {
            myTcpClient.BeginSend(m_pSendBytes.bytes, m_pSendBytes.position, m_pSendBytes.length - m_nSendByteNumber, 0, new AsyncCallback(SendCallback), null);
            m_pSendBytes.position += m_pSendBytes.length - m_nSendByteNumber;
            return true;
        }
        catch (Exception e)
        {//发送失败
            Close();
            Debug.Log("send"+e.Message);
            return false;
        }
    }



    /// <summary>
    /// 发送回调函数
    /// </summary>
    /// <param name="asyncResult"></param>
    private void SendCallback(IAsyncResult asyncResult)
    {
        lock (m_pLock)
        {
            try
            {
                int sended = myTcpClient.EndSend(asyncResult);
                m_nSendByteNumber += sended;
                if (m_nSendByteNumber > m_pSendBytes.length)
                {
                    return;
                }
                else if (m_nSendByteNumber == m_pSendBytes.length)
                {
                    m_nSendByteNumber = 0;
                    m_pSendBytes.Clear();
                    if (m_szWaitData.Count <= 0) {
                       // Debug.Log("finish");
                        sendList.RemoveFirst();
                        asyncwrite();
                        return;
                    }
                    m_pSendBytes.WriteBytes(m_szWaitData[0], 0, m_szWaitData[0].length);
                    m_pSendBytes.position = 0;
                    m_szWaitData.RemoveAt(0);
                }
                else
                {
                    m_pSendBytes.position = m_nSendByteNumber;
                }
                OnSend();
            }
            catch (Exception e)
            {
                Close();
                Debug.Log("send" + e.Message);
            }
        }
    }

    public void UnInit()
    {
        m_bRun = false;
        stop();
        
        if (myTcpClient!=null)
          myTcpClient.Close();
    }


    public void Open(string IpAddr, int port)
    {
        try
        {
            connectDone.Reset();
            myTcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress serverIp = IPAddress.Parse(IpAddr);
            IPEndPoint iep = new IPEndPoint(serverIp, port);
            myTcpClient.BeginConnect(iep, new AsyncCallback(ConnectCallback), myTcpClient);//异步connect
            connectDone.WaitOne();

        }
        catch (SocketException ex)
        {
            Debug.Log(ex.Message);
        }
    }

    private void ConnectCallback(IAsyncResult ar)
    {
        connectDone.Set();
        Socket client = (Socket)ar.AsyncState;
        if (client.Connected)
        {
            client.EndConnect(ar);
            SocketManager.GetInstance().PushEvent(EvtType.netevt_establish);
            Debug.Log("连接成功");
        }
        else
        {
            SocketManager.GetInstance().PushEvent(EvtType.netevt_fail);
            Debug.Log("连接失败");
        }
    }

    public void Close()
    {
		myTcpClient.Close();
        SocketManager.GetInstance().PushEvent(EvtType.netevt_fail);
    }

	public override void abort() {
		m_bRun = false;
	}

    public override void run()
    {
        if (m_bRun)
        {
            if (SocketManager.GetInstance().GetState() == SocketState.state_connectok)
            {
                asyncwrite();
                asyncread();
            }
        }
    }

    public bool Send(GameMsg gameMsg) {
        if (gameMsg == null)
            return false;
           sendList.AddLast(gameMsg);
        return false;
    }

    public bool SendNow(GameMsg gameMsg)
    {
        if (gameMsg == null)
            return false;
        sendList.AddFirst(gameMsg);
        return false;
    }

    public byte[] encoder(GameMsg gameMsg) {
        int contentLen = gameMsg.Content.ReadableBytes();
        int headLen = 2 + contentLen;
        ByteBuffer buff = ByteBuffer.Allocate(10);
        buff.WriteInt(headLen);
        buff.WriteShort(gameMsg.Code);
        buff.WriteBytes(gameMsg.Content.ToArray());
        byte[] sendData = buff.ToArray();
        return sendData;
    }

   
}


